package cn.iocoder.yudao.module.mini.service.technician;

import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.mini.dal.dataobject.healthy.HealthyDO;
import cn.iocoder.yudao.module.mini.dal.dataobject.user.UserDO;
import cn.iocoder.yudao.module.mini.dal.mysql.healthy.HealthyMapper;
import cn.iocoder.yudao.module.mini.dal.mysql.user.MiniUserMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import cn.iocoder.yudao.module.mini.enums.ErrorCodeConstants;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.util.*;
import java.util.stream.Collectors;

import cn.iocoder.yudao.module.mini.controller.admin.technician.vo.*;
import cn.iocoder.yudao.module.mini.dal.dataobject.technician.TechnicianDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;

import cn.iocoder.yudao.module.mini.convert.technician.TechnicianConvert;
import cn.iocoder.yudao.module.mini.dal.mysql.technician.TechnicianMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;

/**
 * 技师 Service 实现类
 *
 * @author dzy
 */
@Service
@Validated
public class TechnicianServiceImpl implements TechnicianService {

    @Resource
    private TechnicianMapper technicianMapper;

    @Resource
    private MiniUserMapper miniUserMapper;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private HealthyMapper healthyMapper;

    @Override
    @Transactional
    public Long createTechnician(TechnicianCreateReqVO createReqVO) {

        UserDO userDO = memberUserHandle(createReqVO);
        miniUserMapper.insert(userDO);
        TechnicianDO technician = TechnicianConvert.INSTANCE.convert(createReqVO);

        // 技师新增
        technician.setMemberId(userDO.getId());
        technicianMapper.insert(technician);

        // 健康档案新增
        healthyMapper.insert(new HealthyDO().setMemberId(userDO.getId()));

        return technician.getId();
    }

    private UserDO memberUserHandle(TechnicianCreateReqVO createReqVO) {
        return new UserDO().setAvatar(createReqVO.getAvatar())
                .setMobile(createReqVO.getMobile())
                .setNickname(createReqVO.getNickname())
                .setRole("technician")
                .setIdCard(createReqVO.getIdCard())
                .setMobile(createReqVO.getMobile())
                .setSex(createReqVO.getSex())
                .setRegisterIp(ServletUtils.getClientIP())
                .setAreaCode(String.join(",",createReqVO.getAreaCodeList()))
                .setStatus(0)
                .setPassword(passwordEncoder.encode(createReqVO.getPassword()));
    }

    @Override
    @Transactional
    public void updateTechnician(TechnicianUpdateReqVO updateReqVO) {
        // 校验存在
        validateTechnicianExists(updateReqVO.getId());

        UserDO userDO = updateReqVOHandle(updateReqVO);
        miniUserMapper.updateById(userDO);

        // 更新
        TechnicianDO updateObj = TechnicianConvert.INSTANCE.convert(updateReqVO);
        technicianMapper.updateById(updateObj);
    }

    private UserDO updateReqVOHandle(TechnicianUpdateReqVO updateReqVO) {
        return new UserDO()
                .setId(updateReqVO.getMemberId())
                .setAvatar(updateReqVO.getAvatar())
                .setMobile(updateReqVO.getMobile())
                .setNickname(updateReqVO.getNickname())
                .setRole("technician")
                .setIdCard(updateReqVO.getIdCard())
                .setMobile(updateReqVO.getMobile())
                .setSex(updateReqVO.getSex())
                .setAreaCode(String.join(",",updateReqVO.getAreaCodeList()))
                .setRegisterIp(ServletUtils.getClientIP())
                .setStatus(0)
                .setPassword(passwordEncoder.encode(updateReqVO.getPassword()));
    }

    @Override
    @Transactional
    public void deleteTechnician(Long id) {
        // 校验存在
        validateTechnicianExists(id);
        // 删除
        TechnicianDO technicianDO = technicianMapper.selectById(id);
        miniUserMapper.deleteById(technicianDO.getMemberId());
        healthyMapper.delete(new LambdaQueryWrapperX<HealthyDO>().eq(HealthyDO::getMemberId, technicianDO.getMemberId()));
        technicianMapper.deleteById(id);

    }

    private void validateTechnicianExists(Long id) {
        if (technicianMapper.selectById(id) == null) {
            throw exception(ErrorCodeConstants.TECHNICIAN_NOT_EXISTS);
        }
    }

    @Override
    public TechnicianDO getTechnician(Long id) {
        return technicianDOHandle(technicianMapper.selectById(id));
    }

    private TechnicianDO technicianDOHandle(TechnicianDO technicianDO) {
        UserDO userDO = miniUserMapper.selectById(technicianDO.getMemberId());
        technicianDO.setNickname(userDO.getNickname());
        technicianDO.setMobile(userDO.getMobile());
        technicianDO.setIdCard(userDO.getIdCard());
        technicianDO.setAvatar(userDO.getAvatar());
        technicianDO.setSex(userDO.getSex());
        technicianDO.setMemberId(userDO.getId());
        List<Long> AreaCodeList = Arrays.stream(userDO.getAreaCode().split(",")).map(Long::parseLong).collect(Collectors.toList());
        technicianDO.setAreaCodeList(AreaCodeList);
        return technicianDO;
    }

    @Override
    public List<TechnicianDO> getTechnicianList(Collection<Long> ids) {
        return technicianMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<TechnicianDO> getTechnicianPage(TechnicianPageReqVO pageReqVO) {

        if (Objects.nonNull(pageReqVO.getNickname())) {
            List<UserDO> memberIds = new ArrayList<>(miniUserMapper.selectList(new LambdaQueryWrapper<UserDO>().select(UserDO::getId).like(UserDO::getNickname, pageReqVO.getNickname())));
            pageReqVO.setMemberIds(memberIds.stream().map(UserDO::getId).collect(Collectors.toList()));
        }
        PageResult<TechnicianDO> technicianDOPageResult = technicianMapper.selectPage(pageReqVO);
        technicianDOPageResult.getList().forEach(item -> {
            UserDO userDO = miniUserMapper.selectById(item.getMemberId());
            item.setNickname(userDO.getNickname());
            item.setIdCard(userDO.getIdCard());
            item.setAvatar(userDO.getAvatar());
            item.setMobile(userDO.getMobile());
            item.setPassword(userDO.getPassword());
        });
        return technicianDOPageResult;
    }

    @Override
    public List<TechnicianDO> getTechnicianList(TechnicianExportReqVO exportReqVO) {
        return technicianMapper.selectList(exportReqVO);
    }

}
